package com.db.stockexchange.client;


/**
 * 
 * @author Rayman
 * Stock for sell/buy
 */
public class Stock {
	static final String MES_ILLEGAL_SHARE_NUMBER = "Share number is illegal. It should be positive integer value";
	static final String MES_ILLEGAL_PRICE = "Price is illegal. It should be positive value";
	
	private int id;
	private String name;
	private StockOperation operation;
	private int shareNumber;
	private boolean useBestMarketPrice;
	private float price;
	private StockState state;
	private int filledShareNumber;
	private int leftShareNumber;

	/**
	 * Create stock with specifying price
	 * @param name Name of stock
	 * @param operation Type of operation {@link StockOperation}
	 * @param shareNumber Number of shares
	 * @param price Price that client would operate with
	 */
	public Stock(String name, StockOperation operation, int shareNumber, float price) throws IllegalStockException {
		super();
		if(checkShareNumber(shareNumber))
			this.shareNumber = shareNumber;
		
		if (checkPrice(price))
			this.price = price;
			
		this.name = name;
		this.operation = operation;
		this.useBestMarketPrice = false;
	}
	
	/**
	 * Create stock with best market price
	 * @param name Name of stock
	 * @param operation Type of operation {@link StockOperation}
	 * @param shareNumber Number of shares
	 */
	public Stock(String name, StockOperation operation, int shareNumber) throws IllegalStockException {
		super();
		if(checkShareNumber(shareNumber))
			this.shareNumber = shareNumber;
		
		this.name = name;
		this.operation = operation;
		this.shareNumber = shareNumber;
		this.useBestMarketPrice = true;
		this.price = Float.NaN;
	}
	
	public int getId() {
		return id;
	}
	
	void setId(int id) {
		this.id = id;
	}

	public int getShareNumber() {
		return shareNumber;
	}

	public void setShareNumber(int shareNumber) throws IllegalStockException {
		if(checkShareNumber(shareNumber))
			this.shareNumber = shareNumber;
	}

	public boolean isUseBestMarketPrice() {
		return useBestMarketPrice;
	}

	/**
	 * Enable using best market price
	 */
	public void useBestMarketPrice() {
		this.useBestMarketPrice = true;
		this.price = Float.NaN;
	}
	
	/**
	 * Disable using best market price and set specified price
	 * @param price Specified price
	 */
	public void useSpecifiedPrice(float price) throws IllegalStockException {
		if (checkPrice(price))
			this.price = price;
		
		useBestMarketPrice = false;
	}

	public float getPrice() {
		return price;
	}

	public String getName() {
		return name;
	}

	public StockOperation getOperation() {
		return operation;
	}
	
	public StockState getState() {
		return state;
	}

	void setState(StockState state) {
		this.state = state;
	}
	
	int getFilledShareNumber() {
		return filledShareNumber;
	}

	void setFilledShareNumber(int filledShareNumber) {
		this.filledShareNumber = filledShareNumber;
	}

	int getLeftShareNumber() {
		return leftShareNumber;
	}

	void setLeftShareNumber(int leftShareNumber) {
		this.leftShareNumber = leftShareNumber;
	}
	
	private boolean checkShareNumber(int shareNumber) throws IllegalStockException {
		if (shareNumber <= 0)
			throw new IllegalStockException(MES_ILLEGAL_SHARE_NUMBER);
		
		return true;
	}
	
	private boolean checkPrice(float price) throws IllegalStockException {
		if (Float.isNaN(price) || price <= 0)
			throw new IllegalStockException(MES_ILLEGAL_PRICE);
		
		return true;
	}
	
	@Override
	public String toString() {
		return new StringBuilder().append(id).append(":")
				.append(name).append(":")
				.append(operation).append(":")
				.append(shareNumber).append(":")
				.append(useBestMarketPrice ? "market" : price).append(":")
				.append(state).append(":")
				.append(filledShareNumber).append(":")
				.append(leftShareNumber).toString();
	}
}
